<template>
	<div class="container" @mousedown="startPan" @mousemove="doPan" @mouseup="endPan" @wheel="onWheel">
		<!-- <div class="container" @mousedown="startPan" > -->
		<svg :width="svgWidth" :height="svgHeight"
			:viewBox="`${viewBox.minX} ${viewBox.minY} ${viewBox.width} ${viewBox.height}`">
			<defs>
				<marker id="arrowhead" markerWidth="3" markerHeight="5" refX="4" refY="2.5" orient="auto">
					<polygon points="0 0, 2 2.5, 0 5" :fill="selectedEdge?.color || '#1890ff'" />
				</marker>
				<marker id="arrow-start" markerWidth="3" markerHeight="5" refX="1" refY="2.5" orient="auto">
					<polygon points="0 0, 2 2.5, 0 5" :fill="selectedEdge?.color || '#1890ff'" />
				</marker>
			</defs>
			<g v-for="edge in edges" :key="edge.id">
				<line :x1="edge.startX" :y1="edge.startY" :x2="edge.endX" :y2="edge.endY" :stroke="edge.color"
					stroke-width="8" marker-end="url(#arrowhead)" class="edge-line" @click.stop="selectEdge(edge)" />
				<line v-if="edge.isBidirectional" :x1="edge.endX" :y1="edge.endY" :x2="edge.startX" :y2="edge.startY"
					:stroke="edge.color" stroke-width="8" marker-end="url(#arrowhead)" @click.stop="selectEdge(edge)" />
			</g>
			<g v-for="(point, index) in points" :key="index" @click="selectPoint(point)" class="point-group">
				<circle :cx="point.x" :cy="point.y" r="15" class="point-circle"
					:class="{'start-point': isStartPoint(point),'end-point': isEndPoint(point)}" />
				<image :x="point.x - 10" :y="point.y - 10" :width="20" :height="20"
					:xlink:href="getIconPath(point.pointType)" class="point-icon" />
				<text :x="point.x + 15" :y="point.y - 15" class="point-label">
					{{ point.pointName }}
				</text>
			</g>
		</svg>
		<!-- 边编辑面板 -->
		<div v-if="selectedEdge" class="edge-edit-panel"
			:style="{left: edgePanelPos.x + 'px', top: edgePanelPos.y + 'px'}">
			<div class="panel-header" @mousedown="startEdgeDrag">
				<span class="title">编辑面板</span>
				<span class="edge-id">ID: {{ selectedEdge.id }}</span>
				<el-button class="close-btn" type="danger" size="large" @click.stop="closePanel">
					×
				</el-button>
			</div>
			<div class="panel-body">
				<el-form label-width="120px" :model="selectedEdge">
					<!-- 基本信息 -->
					<!-- 可编辑字段 -->
					<el-form-item label="距离（米）" prop="distance" :rules="[{ required: true, message: '距离不能为空' },
                           { type: 'number', min: 0.1, message: '距离需大于0' }]">
						<el-input-number v-model="selectedEdge.distance" :min="0.1" :step="0.1"
							controls-position="right" />
					</el-form-item>

					<el-form-item label="默认速度米每秒" prop="defaultSpeed">
						<el-input-number v-model="selectedEdge.defaultSpeed" :min="0" :step="0.5"
							controls-position="right" />
					</el-form-item>
					
					<el-form-item label="基准通行时间" prop="timeLockThreshold">
						<el-input-number v-model="selectedEdge.timeLockThreshold" :min="0" :step="0.5"
							controls-position="right" />
					</el-form-item>

					<el-form-item label="双向通行" prop="isBidirectional">
						<el-switch v-model="selectedEdge.isBidirectional" />
					</el-form-item>

					<el-form-item label="激活状态" prop="isActive">
						<el-switch v-model="selectedEdge.isActive" />
					</el-form-item>

					<el-form-item label="限制条件" prop="restriction">
						<el-input v-model="selectedEdge.restriction" placeholder="例如：限高2.5米,限重3吨" />
					</el-form-item>

					<!-- 只读字段 -->
					<el-form-item label="最后更新时间" prop="updateTime">
						<el-input :value="selectedEdge.updateTime" disabled />
					</el-form-item>

					<el-form-item>
						<el-button type="primary" @click="saveEdge">保存修改</el-button>
						<el-button @click="confirmDelete">删除该边</el-button>
					</el-form-item>
				</el-form>
			</div>
		</div>
		<!-- 选中点位信息展示 -->
		<div v-if="selectedPoint" class="info-card" :style="{left: pos.x + 'px',top: pos.y + 'px'}">
			<div class="header" @mousedown="startDrag">
				<h3>创建面板 (拖动我)</h3>
			</div>
			<div class="content">
				<!-- 当前选中信息 -->
				<section class="current-point">
					<section class="selected-info">
						<div v-if="startPoint" class="selected-item">
							<el-tag type="success" size="small">起点</el-tag>
							<span>{{ startPoint.pointName }}</span>
						</div>
						<div v-if="endPoint" class="selected-item">
							<el-tag type="danger" size="small">终点</el-tag>
							<span>{{ endPoint.pointName }}</span>
						</div>
					</section>
					<!-- 操作按钮 -->
					<div class="action-buttons">
						<el-button type="success" plain @click="setAsStart">
							设为起点
						</el-button>
						<el-button type="danger" plain @click="setAsEnd">
							设为终点
						</el-button>
					</div>
				</section>
				<div class="action-group">
					<el-button type="primary" :disabled="!startPoint || !endPoint || isLoading"
						:class="{ 'highlight-button': startPoint && endPoint }" @click="handlePathPlanning">
						{{ isLoading ? '加载中...' : '创建边' }}
					</el-button>
					<el-button v-if="startPoint || endPoint" type="info" @click="clearPoints" plain>
						清空起终点
					</el-button>
					<el-button v-if="isLoading" type="danger" @click="cancelPathPlanning" class="cancel-button">
						取消规划
					</el-button>
				</div>

			</div>
		</div>

	</div>

</template>

<script setup>
	import {
		ref,
		reactive,
		onMounted,
		computed,
		onUnmounted,
		watch
	} from 'vue';
	import {
		ElMessage
	} from 'element-plus';
	import {
		wcao,
		post,
		rgvpost
	} from "@/http";
	import axios from 'axios';
	import './css/zhi0225.css';
	import {
		Location,
		Place
	} from '@element-plus/icons-vue'
	const selectedEdge = ref(null); // 新增选中边状态
	// 视图框配置
	const viewBox = reactive({
		minX: 0,
		minY: 0,
		width: 1000,
		height: 1000
	});
	// 新增状态：平移与缩放控制
	const svgPanZoom = reactive({
		isPanning: false,
		startX: 0,
		startY: 0,
		scale: 1, // 当前缩放比例
		offsetX: 0, // X轴平移量
		offsetY: 0, // Y轴平移量
		viewBoxCache: {
			...viewBox
		}
	});
	// 导入图片（将你的图片放在public/icons目录下）
	const iconMap = {
		'CAR': '/icons/car.svg',
		'WAREHOUSE': '/icons/ku.svg',
		'TRANSFER': '/icons/zhuan.svg',
		'DEFAULT': '/icons/default.svg'
	};

	// 新增图标获取方法
	const getIconPath = (type) => {
		return iconMap[type] || iconMap.DEFAULT;
	};
	const edgePanelPos = ref({
		x: window.innerWidth / 2 - 150,
		y: window.innerHeight / 2 - 100
	});

	// 新增边面板拖动状态
	const edgeDragging = ref(false);
	let edgeStartX = 0;
	let edgeStartY = 0;
	let edgeInitialPos = {
		x: 0,
		y: 0
	};
	// 边面板拖动方法
	const startEdgeDrag = (e) => {
		edgeDragging.value = true;
		edgeStartX = e.clientX;
		edgeStartY = e.clientY;
		edgeInitialPos = {
			...edgePanelPos.value
		};

		document.addEventListener('mousemove', onEdgeDrag);
		document.addEventListener('mouseup', stopEdgeDrag);
	};

	const onEdgeDrag = (e) => {
		if (!edgeDragging.value) return;

		const dx = e.clientX - edgeStartX;
		const dy = e.clientY - edgeStartY;

		edgePanelPos.value = {
			x: edgeInitialPos.x + dx,
			y: edgeInitialPos.y + dy
		};
	};
	// -------------------------------放大缩小
	// 容器添加 @wheel 事件监听（需要绑定到template中的div.container）
	const onWheel = (e) => {
		// e.preventDefault();
		const delta = e.deltaY > 0 ? 0.9 : 1.1;
		const rect = e.target.getBoundingClientRect();
		const mouseX = (e.clientX - rect.left) / svgPanZoom.scale;
		const mouseY = (e.clientY - rect.top) / svgPanZoom.scale;

		// 更新缩放比例（限定范围）
		svgPanZoom.scale = Math.min(Math.max(0.2, svgPanZoom.scale * delta), 5);

		// 计算焦点偏移量实现中心缩放
		svgPanZoom.offsetX = mouseX - (mouseX - svgPanZoom.offsetX) * delta;
		svgPanZoom.offsetY = mouseY - (mouseY - svgPanZoom.offsetY) * delta;

		// 更新viewBox
		applyViewBoxTransform();
	};
	const stopEdgeDrag = () => {
		edgeDragging.value = false;
		document.removeEventListener('mousemove', onEdgeDrag);
		document.removeEventListener('mouseup', stopEdgeDrag);
	};
	// 在template的div.container上绑定 @mousedown.stop @mousemove @mouseup
	const startPan = (e) => {
		if (e.button !== 1 && e.button !== 0) return; // 仅响应左键/中键拖拽
		svgPanZoom.isPanning = true;
		svgPanZoom.startX = e.clientX - svgPanZoom.offsetX;
		svgPanZoom.startY = e.clientY - svgPanZoom.offsetY;
	};

	const doPan = (e) => {
		if (!svgPanZoom.isPanning) return;
		svgPanZoom.offsetX = e.clientX - svgPanZoom.startX;
		svgPanZoom.offsetY = e.clientY - svgPanZoom.startY;
		applyViewBoxTransform();
	};

	const endPan = () => {
		svgPanZoom.isPanning = false;
	};

	// 合并自动计算与手动偏移
	const applyViewBoxTransform = () => {
		viewBox.minX = svgPanZoom.viewBoxCache.minX - svgPanZoom.offsetX;
		viewBox.minY = svgPanZoom.viewBoxCache.minY - svgPanZoom.offsetY;
		viewBox.width = svgPanZoom.viewBoxCache.width / svgPanZoom.scale;
		viewBox.height = svgPanZoom.viewBoxCache.height / svgPanZoom.scale;
	};

	// ------------------------------------放大缩小
	// 修改关闭面板方法
	const closePanel = () => {
		selectedEdge.value = null;
		edgePanelPos.value = {
			x: window.innerWidth / 2 - 150,
			y: window.innerHeight / 2 - 100
		};
	};
	// SVG画布尺寸
	const svgWidth = ref(window.innerWidth);
	const svgHeight = ref(window.innerHeight);
	const points = ref([]);
	const selectedPoint = ref(null);
	const startPoint = ref(null);
	const endPoint = ref(null);
	const pathPoints = ref([]);
	const isLoading = ref(false);
	const abortController = ref(null);
	// 新增拖动相关状态
	const pos = ref({
		x: 20,
		y: 20
	});
	const dragging = ref(false);
	const startX = ref(0);
	const startY = ref(0);
	const initialPos = ref({
		x: 0,
		y: 0
	});
	const edges = ref([]);
	// 计算属性
	const isCurrentStart = computed(() =>
		selectedPoint.value?.id === startPoint.value?.id
	)

	const isCurrentEnd = computed(() =>
		selectedPoint.value?.id === endPoint.value?.id
	)
	// 方法
	const isStartPoint = (point) =>
		point.id === startPoint.value?.id

	const isEndPoint = (point) =>
		point.id === endPoint.value?.id
	// 新增窗口大小处理
	const handleResize = () => {
		svgWidth.value = window.innerWidth;
		svgHeight.value = window.innerHeight;
	};
	const startDrag = (e) => {
		dragging.value = true;
		startX.value = e.clientX;
		startY.value = e.clientY;
		initialPos.value = {
			...pos.value
		};

		// 添加全局事件监听
		document.addEventListener('mousemove', onDrag);
		document.addEventListener('mouseup', stopDrag);
	};
	const onDrag = (e) => {
		if (!dragging.value) return;

		const dx = e.clientX - startX.value;
		const dy = e.clientY - startY.value;

		pos.value = {
			x: initialPos.value.x + dx,
			y: initialPos.value.y + dy
		};
	};

	const stopDrag = () => {
		dragging.value = false;
		document.removeEventListener('mousemove', onDrag);
		document.removeEventListener('mouseup', stopDrag);
	};
	// 点位选择处理
	const selectPoint = (point) => {
		selectedPoint.value = selectedPoint.value?.id === point.id ?
			null :
			point;
	};
	// 判断特殊点位
	const isSpecialPoint = (point) => {
		return point.id === startPoint.value?.id ||
			point.id === endPoint.value?.id;
	};

	// 设置起点终点
	const setAsStart = () => {
		startPoint.value = selectedPoint.value;
		ElMessage.success(`已设置起点：${selectedPoint.value.pointName}`);
	};

	const setAsEnd = () => {
		endPoint.value = selectedPoint.value;
		ElMessage.success(`已设置终点：${selectedPoint.value.pointName}`);
	};
	// 新增边选择方法
	const selectEdge = (edge) => {
		console.log('选择边');

		selectedEdge.value = {
			...edge
		}; // 创建副本避免直接修改原始数据
	};
	const formatTime = (time) => {
		return time ? dayjs(time).format('YYYY-MM-DD HH:mm:ss') : '未记录';
	};
	// 新增保存边方法
	const saveEdge = async () => {
		try {
			const {
				id,
				distance,
				defaultSpeed,
				isBidirectional,
				isActive,timeLockThreshold,
				restriction
			} = selectedEdge.value;

			await axios.put(`/edge/update/${id}`, {
				distance: Number(distance),
				defaultSpeed: Number(defaultSpeed),
				timeLockThreshold:Number(timeLockThreshold),
				isBidirectional: Boolean(isBidirectional),
				isActive: Boolean(isActive),
				restriction: restriction?.trim()
			});
			// 更新本地数据
			const index = edges.value.findIndex(e => e.id === id);
			edges.value.splice(index, 1, {
				...edges.value[index],
				...selectedEdge.value,
				updateTime: new Date().toISOString()
			});

			ElMessage.success('修改成功');
			closePanel();
		} catch (error) {
			ElMessage.error(`保存失败: ${error.response?.data?.message || error.message}`);
		}
	};
	// 确认删除
	const confirmDelete = () => {
		ElMessageBox.confirm('确定要永久删除该边吗？', '警告', {
			confirmButtonText: '确认删除',
			cancelButtonText: '取消',
			type: 'warning'
		}).then(deleteEdge);
	};
	// 执行删除
	const deleteEdge = async () => {
		try {
			await axios.delete(`/edge/delete/${selectedEdge.value.id}`);
			edges.value = edges.value.filter(e => e.id !== selectedEdge.value.id);
			ElMessage.success('边删除成功');
			closePanel();
		} catch (error) {
			ElMessage.error('删除失败: ' + error.message);
		}
	};
	// 边数据生成
	const handlePathPlanning = async () => {
		try {
			isLoading.value = true;
			abortController.value = new AbortController();
			console.log('开始生成路径');
			const response = await axios.post('/edge/insert', {
				start: startPoint.value,
				end: endPoint.value
			}, {
				signal: abortController.value.signal
			});
			ElMessage.success('添加成功');
		} catch (error) {
			if (!axios.isCancel(error)) {
				ElMessage.error('添加失败');
				console.error('添加错误:', error);
			}
		} finally {
			isLoading.value = false;
			abortController.value = null;
			fetchEdges();
		}
	};
	// 更新路径计算
	const pathData = computed(() => {
		if (pathPoints.value.length === 0) return '';
		return pathPoints.value
			.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`)
			.join(' ');
	});
	// 清空起终点
	const clearPoints = () => {
		startPoint.value = null;
		endPoint.value = null;
		pathPoints.value = [];
		ElMessage.info('已清空起终点');
	};

	// 取消添加路径
	const cancelPathPlanning = () => {
		if (abortController.value) {
			abortController.value.abort();
			ElMessage.warning('已取消添加');
		}
		isLoading.value = false;
		pathPoints.value = [];
	};

	// 路径生成计算属性
	const loadpathData = computed(() => {
		if (points.value.length === 0) return '';
		return points.value
			.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`)
			.join(' ');
	});
	const fetchPoints = async () => {
		try {
			let response = await axios.post('/points/getAll'); // 替换为实际的 API 地址
			console.log('加载点位个数:' + response.data.length);
			if (!Array.isArray(response.data)) {
				throw new Error(`无效的响应类型，预期数组，实际得到: ${typeof response.data}`);
			}
			// 数据转换
			let validPoints = response.data
				.map(p => ({
					id: Number(p.id),
					pointName: p.pointName || '未命名',
					pointType: p.pointType || 'DEFAULT',
					x: Number(p.locationX) || 0,
					y: Number(p.locationY) || 0,
					nodeId: p.nodeId
				}))
				.filter(p => Number.isInteger(p.id) && p.id > 0);
			// 更新状态
			points.value = validPoints;
		} catch (error) {
			console.log('加载失败:', error);
			ElMessage.error(`加载失败,仅展示默认的点位示例`);
			points.value = [{
					id: 1,
					x: 100,
					y: 100,
					pointType: 'CAR',
					pointName: '车辆点位'
				},
				{
					id: 2,
					x: 200,
					y: 150,
					pointType: 'WAREHOUSE',
					pointName: '仓库点位'
				},
				{
					id: 3,
					x: 300,
					y: 300,
					pointType: 'TRANSFER',
					pointName: '旋转点位'
				}
			];
		}
	};
	//*********************************************获取边的数据******************************************************
	const fetchEdges = async () => {
		try {
			let response = await axios.get('/edge/getAll');
			let rawData = response.data?.data || [];
			edges.value = rawData.map(edge => {
				let startPoint = points.value.find(p => p.id === edge.fromPointId);
				let endPoint = points.value.find(p => p.id === edge.toPointId);
				if (!startPoint || !endPoint) {
					console.warn('边数据不完整，跳过绘制:', edge.id);
					return null;
				}
				return {
					id: edge.id,
					startX: startPoint.x,
					startY: startPoint.y,
					endX: endPoint.x,
					endY: endPoint.y,
					distance: edge.distance,
					defaultSpeed: edge.defaultSpeed,
					isActive: edge.isActive,
					restriction: edge.restriction,
					timeLockThreshold:edge.timeLockThreshold,
					updateTime: edge.updateTime,
					color: edge.color || '#1890ff',
					isBidirectional: Boolean(edge.isBidirectional)
				};
			}).filter(Boolean); // 过滤无效数据

			updateViewBox(); // 更新视图框
		} catch (err) {
			console.error('边数据加载失败', err);
			ElMessage.error(`边数据加载失败: ${err.response?.data?.message || err.message}`);
		}
	};


	// 更新视图框
	const updateViewBox = () => {
		const allVisiblePoints = [
			...points.value,
			...edges.value.flatMap(edge => [{
					x: edge.startX,
					y: edge.startY
				},
				{
					x: edge.endX,
					y: edge.endY
				}
			])
		];

		const xs = allVisiblePoints.map(p => p.x);
		const ys = allVisiblePoints.map(p => p.y);
		const padding = 50;
		viewBox.minX = Math.min(...xs) - padding;
		viewBox.minY = Math.min(...ys) - padding;
		viewBox.width = Math.max(...xs) - viewBox.minX + padding * 2;
		viewBox.height = Math.max(...ys) - viewBox.minY + padding * 2;
		svgPanZoom.viewBoxCache = {
			minX: viewBox.minX,
			minY: viewBox.minY,
			width: viewBox.width,
			height: viewBox.height
		};
		// 应用当前手动调整的参数
		applyViewBoxTransform();
	};
	//***************************************************************************************************
	// 组件挂载时获取初始数据
	onMounted(() => {
		document.title = '路径管理页面';
		fetchPoints().then(() => {
			fetchEdges(); // 确保先有点数据
		});
		// 添加窗口resize监听
		window.addEventListener('resize', updateViewBox);
		window.addEventListener('resize', handleAutoResize);
	})
	// 组件卸载时取消请求
	onUnmounted(() => {
		if (abortController.value) {
			abortController.value.abort();
		}
		window.removeEventListener('resize', updateViewBox);
		window.removeEventListener('resize', handleAutoResize);
	});
	const handleAutoResize = () => {
		svgWidth.value = window.innerWidth;
		svgHeight.value = window.innerHeight;
		updateViewBox();
	};
</script>

<style scoped>
	/* 边样式 */
	line {
		transition: stroke 0.3s ease;
		cursor: pointer;
	}

	line:hover {
		stroke-width: 10;
		filter: drop-shadow(0 0 2px currentColor);
	}

	/* 箭头颜色适配 */
	path {
		transition: fill 0.3s ease;
	}

	/* 边线默认样式 */
	.edge-line {
		stroke-linecap: round;
		transition: stroke-opacity 0.3s;

		&:hover {
			stroke-opacity: 0.8;
			cursor: pointer;
		}
	}

	/* 双向边特殊样式 */
	.line-bidirectional {
		marker-start: url(#arrow-start);
		marker-end: url(#arrow-end);
	}

	/* 箭头定义 */
	.arrowhead {
		fill: currentColor;
	}

	.selected-edge {
		stroke-dasharray: 5, 5;
		animation: pulse 1.5s infinite;
	}

	@keyframes pulse {
		0% {
			stroke-opacity: 0.8;
		}

		50% {
			stroke-opacity: 0.4;
		}

		100% {
			stroke-opacity: 0.8;
		}
	}

	.edge-edit-card {
		width: 320px;
		background: rgba(255, 255, 255, 0.9);
		backdrop-filter: blur(5px);
		box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
		z-index: 1000;
	}

	.edge-edit-card .header {
		cursor: move;
		padding: 12px;
		background: #f5f7fa;
		border-bottom: 1px solid #ebeef5;
	}

	.edge-line {
		cursor: pointer;
		transition: all 0.3s ease;

		&:hover {
			stroke-width: 10;
			filter: drop-shadow(0 0 2px currentColor);
		}
	}

	.edge-edit-panel {
		position: fixed;
		padding: 20px;
		border-radius: 8px;
		min-width: 300px;
		cursor: move;
		user-select: none;
		width: 420px;
		background: #fff;
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
		z-index: 2000;
	}

	.panel-header {
		padding-bottom: 12px;
		border-bottom: 1px solid #ebeef5;
		margin-bottom: 15px;
		display: flex;
		justify-content: space-between;
		align-items: center;

		h3 {
			margin: 0;
			font-size: 16px;
		}
	}

	.panel-body {
		padding: 0 20px 20px;

		.el-form-item:last-child {
			margin-bottom: 0;
		}

		.el-form-item {
			margin-bottom: 18px;
		}

		.el-input-number {
			width: 100%;
		}
	}
</style>